package com.jiunuan.live.gateway.filter;

import com.jiunuan.live.account.interfaces.IAccountTokenRpc;
import com.jiunuan.live.common.interfaces.enums.GatewayHeaderEnum;
import com.jiunuan.live.gateway.properties.GatewayApplicationProperties;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

import static io.netty.handler.codec.http.cookie.CookieHeaderNames.MAX_AGE;
import static org.springframework.web.cors.CorsConfiguration.ALL;

@Component
@Slf4j
public class AccountCheckFilter implements GlobalFilter, Ordered {
    @DubboReference
    private IAccountTokenRpc accountTokenRpc;
    @Resource
    private GatewayApplicationProperties gatewayApplicationProperties;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求url，判断是否为空，如果为空返回请求不通过
        ServerHttpRequest request = exchange.getRequest();
        String reqUrl = request.getURI().getPath();
        // cors跨域配置 todo 内容写死
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, gatewayApplicationProperties.getDomain());
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
        headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);


        if(StringUtils.isEmpty(reqUrl)){
            return Mono.empty();
        }
        // 根据url，判断是否存在于url的白名单中，如果存在，则不对token进行校验
        List<String> notCheckUrlList = gatewayApplicationProperties.getNotCheckUrlList();
        for(String notCheckUrl : notCheckUrlList){
            if(reqUrl.contains(notCheckUrl)){
                log.info("[AccountCheckFilter]请求未进行token校验，直接传递给下游业务");
                return chain.filter(exchange);
            }
        }
        // 如果不存在url白名单中，则需要提取cookie，对token的基本格式进行校验
        List<HttpCookie> httpCookieList = request.getCookies().get("JNTK");
        if(CollectionUtils.isEmpty(httpCookieList)){
            log.warn("[AccountCheckFilter]请求不合法，cookie中的JNTK为空");
            return Mono.empty();
        }
        String jiunuanTokenCookiesValue = httpCookieList.get(0).getValue();
        // 判断cookie中的JNTK是否为空(去除空格后仍未空)
        if(StringUtils.isEmpty(jiunuanTokenCookiesValue)||StringUtils.isEmpty(jiunuanTokenCookiesValue.trim())){
            log.warn("[AccountCheckFilter]请求不合法，cookie中的JNTK为空");
            return Mono.empty();
        }
        // token获取到之后，调用rpc判断token是否合法，如果合法把token获取的userId传递给下游
        Long userId = accountTokenRpc.getUserIdByToken(jiunuanTokenCookiesValue);
        if(userId==null){
            log.warn("[AccountCheckFilter]请求token失效，不合法");
            return Mono.empty();
        }
        // gateway --header--> spring boot - web(interceptor --> get header)
        ServerHttpRequest.Builder builder = request.mutate();
        builder.header(GatewayHeaderEnum.USER_LOGIN_ID.getName(),String.valueOf(userId));
        // 如果不合法，则返回请求不通过
        return chain.filter(exchange.mutate().request(builder.build()).build());
    }
    @Override
    public int getOrder() {
        return 0;
    }
}